#include "command.h"
#include "document.h"

#include <iostream>

using namespace std;

CutCommand::CutCommand(Document* pDoc)
{
	m_pDoc = pDoc;
}

void CutCommand::execute()
{
	m_pDoc->cut();
}

void CutCommand::undo()
{
	m_pDoc->undoCut();
}

Command* CutCommand::clone()
{
	CutCommand* pNewCmd = new CutCommand(m_pDoc);
	*pNewCmd = *this;
	return pNewCmd;
}

CommandList::~CommandList()
{
	list<Command*>::iterator it;

	for (it = m_undoList.begin();
		it != m_undoList.end(); ++it)
	{
		delete *it;
	}
	m_undoList.clear();

	for (it = m_redoList.begin();
		it != m_redoList.end(); ++it)
	{
		delete *it;
	}
	m_redoList.clear();
}

void CommandList::add(Command* pCmd)
{
	m_undoList.push_back(pCmd->clone());
	m_redoList.clear();
}

void CommandList::undo()
{
	if (!checkUndo())
	{
		cout<<"Nothing to undo."<<endl;
	} 
	else
	{
		list<Command*>::iterator it;

		it = m_undoList.end();
		--it;

		(*it)->undo();

		m_redoList.push_back(*it);
		m_undoList.erase(it);
	}
}

void CommandList::undoAll()
{
	if (!checkUndo())
	{
		cout<<"Nothing to undo."<<endl;
	} 
	else
	{
		list<Command*>::const_reverse_iterator it;
		for (it = m_undoList.rbegin();
			it != m_undoList.rend(); ++it)
		{
			(*it)->undo();
			m_redoList.push_back(*it);
		}
		m_undoList.clear();
	}
}

void CommandList::redo()
{
	if (!checkRedo())
	{
		cout<<"Nothing to redo."<<endl;
	} 
	else
	{
		list<Command*>::iterator it;
		
		it = m_redoList.end();
		--it;

		(*it)->execute();

		m_undoList.push_back(*it);
		m_redoList.erase(it);
	}
}

void CommandList::redoAll()
{
	if (!checkRedo())
	{
		cout<<"Nothing to redo."<<endl;
	} 
	else
	{
		list<Command*>::const_reverse_iterator it;
		for (it = m_redoList.rbegin();
			it != m_redoList.rend(); ++it)
		{
			(*it)->execute();
			m_undoList.push_back(*it);
		}
		m_redoList.clear();
	}
}

bool CommandList::checkUndo()
{
	return m_undoList.size() > 0;
}

bool CommandList::checkRedo()
{
	return m_redoList.size() > 0;
}
